'''
 * Licensed to the Apache Software Foundation (self, ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (self, the
 * "License") you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http:#www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
'''

'''
import java.util.Map

import org.apache.jena.assembler.JA
import org.apache.jena.shared.impl.PrefixMappingImpl
import org.apache.jena.sys.JenaSystem
import org.apache.jena.vocabulary.*
'''

'''
 * Methods for recording namespace prefix mappings and applying and
 * unapplying them to URIs.
 * <p>
 * Note that a Model *is* a PrefixMapping, so all the PrefixMapping
 * operations apply to Models, and a Model can be used to supply
 * the PrefixMapping argument to setNsPrefixes.
'''

from abc import ABC, abstractmethod

class PrefixMapping(ABC):
    '''
     * Specify the prefix name for a URI prefix string. Any existing use of
     * that prefix name is overwritten. The result is this same prefixMapping.
     * (self, The earlier restriction that adding second prefix for the same URI
     * caused the earlier binding to be deleted has been withdrawn.)
     * <p>
     * A prefix name must be a valid NCName, or the empty string. The empty string
     * is reserved to mean "the default namespace".
     * <p>
     * Need not check the RFC2396 validity of the URI. Bad URIs are either silently
     * ignored or behave as if they were good. The earlier restriction that the URI
     * should end with a non-NCName character has been removed.
     * <p>
     * <p>
     * Note, in particular, that the prefix mapping can only be used
     * if it includes the URI up to any '#' character because '#' is not legal
     * in the local part of an NCName.
     *
     * @param prefix the string to be used for the prefix.
     * @param uri    the URI prefix to be named
     * @return this PrefixMapping
     * @throws IllegalPrefixException if the prefix is not an XML NCName
    '''
    # param String prefix, String uri
    # result PrefixMapping
    @abstractmethod
    def setNsPrefix(self, prefix, uri):
        pass

    '''
     * Remove any existing maplet with the given prefix name and answer this
     * mapping. If the prefix is the empty string, then this removes the default
     * namespace. If the prefix is not a legal prefix string, or is not present in
     * the mapping, nothing happens.
     *
     * <p>The reverse URI-to-prefix mapping is updated, but if there are
     * multiple prefixes for the removed URI it is unspecified which of them
     * will be chosen.
     *
     * @param prefix the prefix string to remove
     * @return this PrefixMapping
    '''

    # param String prefix
    # result PrefixMapping
    @abstractmethod
    def removeNsPrefix(self, prefix):
        pass

    '''
     * Clear this prefix mapping of all mappings
    '''
    # param 
    # result PrefixMapping
    @abstractmethod
    def clearNsPrefixMap(self):
        pass


    '''
     * Copies the prefixes from other into this. Any existing binding of the
     * same prefix is lost.  The result is this same prefixMapping.
     *
     * @param other the PrefixMapping to add
     * @return this PrefixMapping
    '''
    # param PrefixMapping other
    # result PrefixMapping
    @abstractmethod
    def setNsPrefixes(self, other):
        pass

    '''
     * Copies the prefix mapping from other into this. Illegal prefix mappings
     * are detected. Existing binds of the same prefix are lost.  The result is this
     * same prefixMapping.
     *
     * @param map the Map whose maplets are to be added
     * @return this PrefixMapping
    '''
    # param Map<String, String> map
    # result PrefixMapping
    @abstractmethod
    def setNsPrefixes(self, map):
        pass

    '''
     * Update this PrefixMapping with the bindings in <code>map</code>, only
     * adding those (self, p, u) pairs for which neither p nor u appears in this mapping.
     * Answer this PrefixMapping.
    '''
    # param PrefixMapping map
    # result PrefixMapping
    @abstractmethod
    def withDefaultMappings(self, map):
        pass

    '''
     * Get the URI bound to a specific prefix, null if there isn't one.
     *
     * @param prefix the prefix name to be looked up
     * @return the most recent URI bound to that prefix name, null if none
    '''
    # param String prefix
    # result String
    @abstractmethod
    def getNsPrefixURI(self, prefix):
        pass

    '''
     * Answer the prefix for the given URI, or null if there isn't one.
     * If there is more than one, one of them will be picked. If possible,
     * it will be the most recently added prefix. (self, The cases where it's not
     * possible is when a binding has been removed.)
     *
     * @param uri the uri whose prefix is to be found
     * @return the prefix mapped to that uri, or null if there isn't one
    '''
    # param String uri
    # result String
    @abstractmethod
    def getNsURIPrefix(self, uri):
        pass

    '''
     * Return a copy of the internal mapping from names to URI strings. Updating
     * this copy will have no effect on the PrefixMap.
     *
     * @return a copy of the internal String:@literal -> String mapping
    '''
    # param
    # result Map<String, String>
    def getNsPrefixMap(self):
        pass

    '''
     * Expand the uri using the prefix mappings if possible. If prefixed has the
     * form Foo:Bar, and Foo is a prefix bound to FooURI, return FooURI+Bar.
     * Otherwise return prefixed unchanged.
     *
     * @param prefixed a QName or URI
     * @return the expanded string if possible, otherwise the original string
    '''
    # param String prefixed
    # result String
    @abstractmethod
    def expandPrefix(self, prefixed):
        pass

    '''
     * Compress the URI using the prefix mappings if possible. If there is a
     * prefix mapping Name:@literal -> URIStart, and uri is URIStart+Tail, return Name:Tail
     * otherwise return uri unchanged. If there are multiple applicable mappings
     * available, the "most recent" is chosen if that is possible, otherwise
     * one is picked "at random".
     * <p>
     * The result is primarily intended for human convenience: it is <i>not</i>
     * necessarily a legal QName, as Tail need not be a legal NCName and there's
     * no way to tell a shortened name from a URI with an unusual scheme.
     *
     * @param uri the URI string to try and prefix-compress
     * @return the shortened form if possible, otherwise the unchanged argument
    '''
    # param String uri
    # result String
    @abstractmethod
    def shortForm(self, uri):
        pass

    '''
     * Answer a qname with the expansion of the given uri, or null if no such qname
     * can be constructed using the mapping's prefixes.
    '''
    # param String uri
    # result String
    @abstractmethod
    def qnameFor(self, uri):
        pass

    '''
     * Lock the PrefixMapping so that changes can no longer be made to it.
     * Primarily intended to lock Standard against mutation.
     *
     * @return this mapping, locked against changes
    '''
    # param 
    # result PrefixMapping
    @abstractmethod
    def lock(self):
        pass

    # These can not be called the usual "isEmpty" and "size" because this interface is inherited
    # in places where those names are in use for the main putrpose of the interface (self, e.g. Model).

    '''
     * Return whether the prefix mapping has any defined prefixes.
    '''
    # param 
    # result default bolean
    @abstractmethod
    def hasNoMappings(self):
        return self.numPrefixes() == 0
    

    '''
     * Return the number of defined prefixes.
    '''
    # param 
    # result int
    @abstractmethod
    def numPrefixes(self):
        pass

    '''
     * Answer true iff this prefix-mappings are equal, that is, map the same
     * prefixes to the same URIs same as
     * <blockquote>
     * this.getNsPrefixMap(self).equals(self,  other.getNsPrefixMap(self) )
     * </blockquote>
     * except that it may avoid unnecessary Map creations.
    '''
    # param PrefixMapping other
    # result boolean
    @abstractmethod
    def samePrefixMappingAs(self, other):
        pass

